// Author: 		ngohaibac@hocdelam.org
// Date:		23rd Sep, 2009
// Hardware:	TMS320F28335
// Module:		Serial Communication Interface (SCI) 

#include "DSP2833x_Device.h"     // DSP2833x Headerfile Include File
#include "DSP2833x_Examples.h"   // DSP2833x Examples Include File

#include "DSP2833x_System.h"
#include "DSP2833x_SciLib.h"

// Functions used only in this source
void InitSciGpio(void);
void InitSciaGpio(void);
void InitScibGpio(void);
void InitScicGpio(void);

volatile struct SCI_REGS * getSciRegs(enum  SciPorts port);

//================================================================
// Get FIFO buffer size: number of words available in FIFO buffer
//================================================================

Uint16 SCI_getRxBufferSize(enum SciPorts port){
	volatile struct SCI_REGS *SciRegs = getSciRegs(port);
	//Num_Of_Data = ScicRegs.SCIFFRX.bit.RXFFST; 
	return(SciRegs->SCIFFRX.bit.RXFFST);
}

//================================================================
// Write Buffer
//================================================================
/*
void SCI_PrString(enum SciPorts port,Uint16 * buffer, Uint16 len){
	Uint16 i;
	for (i=0;i<len;i++)
		SCI_Write(port,buffer[i]);		
}
*/
void SCI_PrString(enum SciPorts port,char* str){
	while(*str){
		SCI_Write(port,*str++);
	};
}

void SCI_PrHex(enum SciPorts port, Uint16 hex_data,Uint16 number_of_digit){	
	Uint16 buffer[4];
	volatile struct SCI_REGS *SciRegs = getSciRegs(port);
	
	Hex2Ascii(hex_data,buffer);
	while(number_of_digit--)
		SciRegs->SCITXBUF = buffer[number_of_digit];		
}
void SCI_PrDec(enum SciPorts port, Uint16 hex_data,Uint16 number_of_digit){	
	Uint16 buffer[4];
	volatile struct SCI_REGS *SciRegs = getSciRegs(port);
	
	Hex2Dec(hex_data,buffer);
	while(number_of_digit--)
		SciRegs->SCITXBUF = buffer[number_of_digit];		
}
//================================================================
// Write data to SCI Port
//================================================================

void SCI_Write(enum SciPorts port,Uint16 UART_Data){
	volatile struct SCI_REGS *SciRegs = getSciRegs(port);	
	SciRegs->SCITXBUF = UART_Data;
}

//================================================================
// Read data from SCI Port
//================================================================
Uint16 SCI_Read(enum SciPorts port){
	volatile struct SCI_REGS *SciRegs = getSciRegs(port);
	Uint16 RS232_Data;
	
	RS232_Data = SciRegs->SCIRXBUF.all;
	RS232_Data = RS232_Data & 0x00FF;
		
	return (RS232_Data);
} 
//================================================================
// Clear Interrupt flags in Interrupt ISR
//================================================================
void SCI_clearIntFlags(enum SciPorts port){
	volatile struct SCI_REGS *SciRegs = getSciRegs(port);
	
	// Clear Overflag bit, Int flag bit
	SciRegs->SCIFFRX.bit.RXFFOVRCLR = 1;	
	SciRegs->SCIFFRX.bit.RXFFINTCLR = 1;	
	
	// Clear ACK Flag	
	switch(port){
		case SCIA:			
		case SCIB:
			PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;
			break;
		case SCIC:
			PieCtrlRegs.PIEACK.all = PIEACK_GROUP8;
			break;
		default:
			PieCtrlRegs.PIEACK.all = PIEACK_GROUP8;
			break;
	};
	
}
//================================================================
// Initialize Interrupt for SCI
//================================================================
void SCI_InitInt(enum SciPorts port,PINT RxIntFcn){
	// Enable interrupt for each SCI Port
	// SCIA RX = Group 9, bit 1
	// SCIB RX = Group 9, bit 3
	// SCIC RX = Group 8, bit 5
	
	PieCtrlRegs.PIECTRL.bit.ENPIE = 1;			// Enable PIE modules
	switch(port){
		case SCIA:
			PieCtrlRegs.PIEIER9.bit.INTx1 = 1;
			IER |= M_INT9;
			EALLOW;
			PieVectTable.SCIRXINTA = RxIntFcn;
			EDIS;
			break;
		case SCIB:
			PieCtrlRegs.PIEIER9.bit.INTx3 = 1;
			IER |= M_INT9;
			EALLOW;
			PieVectTable.SCIRXINTB = RxIntFcn;
			EDIS;			
			break;
		case SCIC:			
   			PieCtrlRegs.PIEIER8.bit.INTx5 = 1;
   			IER |= M_INT8;
			EALLOW;
			PieVectTable.SCIRXINTC = RxIntFcn;
			EDIS;   			
			break;
		default:
			PieCtrlRegs.PIEIER9.bit.INTx1 = 1;
			IER |= M_INT9;		
			EALLOW;
			PieVectTable.SCIRXINTA = RxIntFcn;
			EDIS;			
			break;
	};
/*	
	// Assign RX Interrupt function
	EALLOW;
	switch(port){
		case SCIA:
			PieVectTable.SCIRXINTA = RxIntFcn;
			break;
		case SCIB:
			PieVectTable.SCIRXINTB = RxIntFcn;
			break;
		case SCIC:
			PieVectTable.SCIRXINTC = RxIntFcn;
			break;
		default:
			PieVectTable.SCIRXINTA = RxIntFcn;
			break;
	};
	EDIS;
*/	
	
}
//================================================================
// Set RxFIFOLevel: Level to generate Interrupt
//================================================================
void SCI_setRxFifoLevel(enum SciPorts port,Uint16 RxFifoLevel){
	volatile struct SCI_REGS *SciRegs = getSciRegs(port);
	union SCIFFRX_REG    shadowSCIFFRX;    // FIFO recieve register
	
	shadowSCIFFRX.bit.RXFFOVRCLR = 1;			// 1: Clear Over flag bit
	shadowSCIFFRX.bit.RXFFINTCLR = 1;			// 1: Clear Int flag bit
	shadowSCIFFRX.bit.RXFIFORESET = 0;			// 0: reset pointer to zero and hold in reset
	shadowSCIFFRX.bit.RXFFIENA = 1;				// 1: Enable RX Interrupt
	shadowSCIFFRX.bit.RXFFIL = 	RxFifoLevel;	// RX Fifo level
	
	SciRegs->SCIFFRX.all = shadowSCIFFRX.all;	
	
	// Re-enable receive FIFO operation
	SciRegs->SCIFFRX.bit.RXFIFORESET = 1;		
}
//================================================================
// Initialize UART with desired baudrate
//================================================================
void SCI_Init(enum SciPorts port, Uint64 BaudRate){
	
	union SCICCR_REG shadowSCICCR;
	union SCICTL1_REG shadowSCICTL1;
	union SCIFFTX_REG    shadowSCIFFTX;    // FIFO transmit register
	union SCIFFRX_REG    shadowSCIFFRX;    // FIFO recieve register	
	
	Uint16 BRR;					// Baud rate
	Uint16 RxFifoLevel = 0x08;
	
	// Assign variable
	volatile struct SCI_REGS *SciRegs = getSciRegs(port);	
	
	// Step 1: Initialize GPIO
	switch(port){
		case SCIA:
			InitSciaGpio();
			break;
		case SCIB:
			InitScibGpio();
			break;
		case SCIC:
			InitScicGpio();
			break;
	};	
	//InitSciGpio();
	
	// Step 2: Config stop, parity, data bits in SCI Communication Control Register (SCICCR)
	shadowSCICCR.bit.STOPBITS 	= 0; 		// 0 = One stop bit, 1 = Two stop bits
	shadowSCICCR.bit.PARITYENA	= 0;		// 0 = Disable parity, 1 = Enable parity
	shadowSCICCR.bit.PARITY		= 0;		// 0 = Odd parity, 1 = even parity
	shadowSCICCR.bit.LOOPBKENA	= 0;		// 0 = Loop back test mode disabled, 1 = Loop back test mode enabled	
	shadowSCICCR.bit.ADDRIDLE_MODE = 0;		// 0 = Idle-line mode protocol ~ RS-232 C standard, 1 = Address-bit mode
	shadowSCICCR.bit.SCICHAR = 0x07;		// (X+1) data bits
	
	SciRegs->SCICCR.all = shadowSCICCR.all;	
	//SciRegs->SCICCR.all = 0x0007;
	// Step 3: Enable trasmitter, receiver, disable TXWAKE, SLEEP, => SCICTRL1 
	
	shadowSCICTL1.bit.RXERRINTENA 	= 0;	// 0 = Disable receive error interrupt, 1 = enable
	shadowSCICTL1.bit.SWRESET	  	= 0;	// 0 = initialize SCI State and flags, 1 = release init state
	shadowSCICTL1.bit.TXWAKE	  	= 0;	// 0 = Disable TXWAKE feature, 1 = enable
	shadowSCICTL1.bit.SLEEP			= 0;	// 0 = Disable SCI Sleep feature, 1 = enable
	
	shadowSCICTL1.bit.TXENA			= 1; 	// 1 = Enable transmitter
	shadowSCICTL1.bit.RXENA			= 1;	// 1 = Enable receiver
	
	SciRegs->SCICTL1.all = shadowSCICTL1.all;	
	//SciRegs->SCICTL1.all = 0x0003;
	
	// Step 4: Set Baudrate
	BRR = LSPCLK_FREQ/(BaudRate*8)-1;
	SciRegs->SCIHBAUD = BRR>>8;
	SciRegs->SCILBAUD = BRR;
	
	// Step 5: Config Interrupt
	// Config interrupt in SCI Control Register 2
	SciRegs->SCICTL2.bit.RXBKINTENA = 1;		// 1 = Enable RXRDY/BRKDT interrupt
	SciRegs->SCICTL2.bit.TXINTENA = 0;			// 0 = Disable TXRDY Interrupt
	
	
	// Config SCI Fifo Transmit Register
	shadowSCIFFTX.bit.SCIRST = 1;
	shadowSCIFFTX.bit.SCIFFENA = 1;				// 1: SCI FIFO enable
	shadowSCIFFTX.bit.TXFFINTCLR = 1; 			// 1: Clear TXFIFINT Flag
	shadowSCIFFTX.bit.TXFFIENA = 0;				// 0: Disable interrupt
	shadowSCIFFTX.bit.TXFFIL = 0x00;			// FIFO Level bit = 0x00
	
	SciRegs->SCIFFTX.all = shadowSCIFFTX.all;
	// SciRegs->SCIFFTX.all = 0xC040;
	
	// FIFO Receive Reg
	shadowSCIFFRX.bit.RXFFOVRCLR = 1;			// 1: Clear Over flag bit
	shadowSCIFFRX.bit.RXFFINTCLR = 1;			// 1: Clear Int flag bit
	shadowSCIFFRX.bit.RXFIFORESET = 0;			// 0: reset pointer to zero and hold in reset
	shadowSCIFFRX.bit.RXFFIENA = 1;				// 1: Enable RX Interrupt
	shadowSCIFFRX.bit.RXFFIL = 	RxFifoLevel;	// RX Fifo level
	
	SciRegs->SCIFFRX.all = shadowSCIFFRX.all;
	
	//SciRegs->SCIFFRX.all = 0x002x			
	
	//Step 6: Relinquish SCI from Reset
	SciRegs->SCICTL1.all = 0x23;				//SciRegs->SCICTL1.bit.SWRESET = 1; 			
	SciRegs->SCIFFTX.bit.TXFIFOXRESET = 1;		// Re-enable transmit FIFO operation
	SciRegs->SCIFFRX.bit.RXFIFORESET = 1;		// Re-enable receive FIFO operation
}
//================================================================
// Get SciRegs
//================================================================
volatile struct SCI_REGS * getSciRegs(enum SciPorts port){
	volatile struct SCI_REGS *SciRegs = &SciaRegs;
	
	switch(port){
		case (SCIA):
			SciRegs = &SciaRegs;
			break;
		case (SCIB):
			SciRegs = &ScibRegs;
			break;
		case (SCIC):
			SciRegs = &ScicRegs;
			break;
		default:
			SciRegs = &SciaRegs;
			break;		
	};
	
	return SciRegs;
}
//================================================================
// Copy from DSP2833x_Sci.c in the Common source

//================================================================
// Iinitialize SCI GPIO
//================================================================
void InitSciGpio()
{
   InitSciaGpio();
#if DSP28_SCIB   
   InitScibGpio();
#endif // if DSP28_SCIB  
#if DSP28_SCIC
   InitScicGpio();
#endif // if DSP28_SCIC
}
//================================================================
// Init GPIO for SCIA
//================================================================
void InitSciaGpio()
{
   EALLOW;

/* Enable internal pull-up for the selected pins */
// Pull-ups can be enabled or disabled disabled by the user.  
// This will enable the pullups for the specified pins.

	GpioCtrlRegs.GPAPUD.bit.GPIO28 = 0;    // Enable pull-up for GPIO28 (SCIRXDA)
	GpioCtrlRegs.GPAPUD.bit.GPIO29 = 0;	   // Enable pull-up for GPIO29 (SCITXDA)

/* Set qualification for selected pins to asynch only */
// Inputs are synchronized to SYSCLKOUT by default.  
// This will select asynch (no qualification) for the selected pins.

	GpioCtrlRegs.GPAQSEL2.bit.GPIO28 = 3;  // Asynch input GPIO28 (SCIRXDA)

/* Configure SCI-A pins using GPIO regs*/
// This specifies which of the possible GPIO pins will be SCI functional pins.

	GpioCtrlRegs.GPAMUX2.bit.GPIO28 = 1;   // Configure GPIO28 for SCIRXDA operation
	GpioCtrlRegs.GPAMUX2.bit.GPIO29 = 1;   // Configure GPIO29 for SCITXDA operation
	
    EDIS;
}
//================================================================
// Init GPIO for SCIB
//================================================================
#if DSP28_SCIB 
void InitScibGpio()
{
   EALLOW;
	
/* Enable internal pull-up for the selected pins */
// Pull-ups can be enabled or disabled disabled by the user.  
// This will enable the pullups for the specified pins.
// Comment out other unwanted lines.

// For RealSys Board, use GPIO9 (SCITXDB) and GPIO11 (SCIRXDB)

	GpioCtrlRegs.GPAPUD.bit.GPIO9 = 0;     // Enable pull-up for GPIO9  (SCITXDB)
//  GpioCtrlRegs.GPAPUD.bit.GPIO14 = 0;    // Enable pull-up for GPIO14 (SCITXDB)
//	GpioCtrlRegs.GPAPUD.bit.GPIO18 = 0;	   // Enable pull-up for GPIO18 (SCITXDB)
//  GpioCtrlRegs.GPAPUD.bit.GPIO22 = 0;    // Enable pull-up for GPIO22 (SCITXDB)

	
	GpioCtrlRegs.GPAPUD.bit.GPIO11 = 0;    // Enable pull-up for GPIO11 (SCIRXDB)
//  GpioCtrlRegs.GPAPUD.bit.GPIO15 = 0;    // Enable pull-up for GPIO15 (SCIRXDB)
//  GpioCtrlRegs.GPAPUD.bit.GPIO19 = 0;	   // Enable pull-up for GPIO19 (SCIRXDB)
//  GpioCtrlRegs.GPAPUD.bit.GPIO23 = 0;    // Enable pull-up for GPIO23 (SCIRXDB)

/* Set qualification for selected pins to asynch only */
// This will select asynch (no qualification) for the selected pins.
// Comment out other unwanted lines.

   	GpioCtrlRegs.GPAQSEL1.bit.GPIO11 = 3;  // Asynch input GPIO11 (SCIRXDB)
//  GpioCtrlRegs.GPAQSEL1.bit.GPIO15 = 3;  // Asynch input GPIO15 (SCIRXDB)
//	GpioCtrlRegs.GPAQSEL2.bit.GPIO19 = 3;  // Asynch input GPIO19 (SCIRXDB)
//  GpioCtrlRegs.GPAQSEL2.bit.GPIO23 = 3;  // Asynch input GPIO23 (SCIRXDB)

/* Configure SCI-B pins using GPIO regs*/
// This specifies which of the possible GPIO pins will be SCI functional pins.
// Comment out other unwanted lines.

  	GpioCtrlRegs.GPAMUX1.bit.GPIO9 = 2;    // Configure GPIO9 for SCITXDB operation
//  GpioCtrlRegs.GPAMUX1.bit.GPIO14 = 2;   // Configure GPIO14 for SCITXDB operation
//	GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 2;   // Configure GPIO18 for SCITXDB operation
//  GpioCtrlRegs.GPAMUX2.bit.GPIO22 = 3;   // Configure GPIO22 for SCITXDB operation
	
  	GpioCtrlRegs.GPAMUX1.bit.GPIO11 = 2;   // Configure GPIO11 for SCIRXDB operation
//  GpioCtrlRegs.GPAMUX1.bit.GPIO15 = 2;   // Configure GPIO15 for SCIRXDB operation
//  GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 2;   // Configure GPIO19 for SCIRXDB operation
//  GpioCtrlRegs.GPAMUX2.bit.GPIO23 = 3;   // Configure GPIO23 for SCIRXDB operation
	
    EDIS;
}
#endif // if DSP28_SCIB 
//================================================================
// Init GPIO for SCIC
//================================================================
#if DSP28_SCIC
void InitScicGpio()
{
   EALLOW;

/* Enable internal pull-up for the selected pins */
// Pull-ups can be enabled or disabled disabled by the user.  
// This will enable the pullups for the specified pins.

	GpioCtrlRegs.GPBPUD.bit.GPIO62 = 0;    // Enable pull-up for GPIO62 (SCIRXDC)
	GpioCtrlRegs.GPBPUD.bit.GPIO63 = 0;	   // Enable pull-up for GPIO63 (SCITXDC)

/* Set qualification for selected pins to asynch only */
// Inputs are synchronized to SYSCLKOUT by default.  
// This will select asynch (no qualification) for the selected pins.

	GpioCtrlRegs.GPBQSEL2.bit.GPIO62 = 3;  // Asynch input GPIO62 (SCIRXDC)

/* Configure SCI-C pins using GPIO regs*/
// This specifies which of the possible GPIO pins will be SCI functional pins.

	GpioCtrlRegs.GPBMUX2.bit.GPIO62 = 1;   // Configure GPIO62 for SCIRXDC operation
	GpioCtrlRegs.GPBMUX2.bit.GPIO63 = 1;   // Configure GPIO63 for SCITXDC operation
	
    EDIS;
}
#endif // if DSP28_SCIC 

	
//===========================================================================
// End of file.
//===========================================================================
